package queryopts

/*
Copyright 2021-2025 The k8gb Contributors.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

Generated by GoLic, for more details see: https://github.com/AbsaOSS/golic
*/

import (
	"fmt"

	k8gbv1beta1 "github.com/k8gb-io/k8gb/api/v1beta1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/types"
	"sigs.k8s.io/controller-runtime/pkg/client"
)

type QueryMode int

const (
	QueryModeGet QueryMode = iota
	QueryModeList
)

type QueryOptions struct {
	Mode     QueryMode
	GetKey   *types.NamespacedName
	ListOpts []client.ListOption
}

// Get creates query options from GSLB ResourceRef
func Get(resourceRef k8gbv1beta1.ResourceRef, namespace string) (*QueryOptions, error) {
	if resourceRef.Name != "" {
		// Direct reference by name - use fallback namespace if ResourceRef namespace is empty
		serviceNamespace := resourceRef.Namespace
		if serviceNamespace == "" {
			serviceNamespace = namespace
		}
		return &QueryOptions{
			Mode: QueryModeGet,
			GetKey: &types.NamespacedName{
				Name:      resourceRef.Name,
				Namespace: serviceNamespace,
			},
		}, nil
	}

	if resourceRef.MatchLabels != nil || resourceRef.MatchExpressions != nil {
		// Reference by label selector
		listOpts := []client.ListOption{
			client.InNamespace(namespace),
		}

		if resourceRef.MatchLabels != nil || resourceRef.MatchExpressions != nil {
			selector, err := metav1.LabelSelectorAsSelector(&resourceRef.LabelSelector)
			if err != nil {
				return nil, fmt.Errorf("invalid label selector: %w", err)
			}
			listOpts = append(listOpts, client.MatchingLabelsSelector{Selector: selector})
		}

		return &QueryOptions{
			Mode:     QueryModeList,
			ListOpts: listOpts,
		}, nil
	}

	return nil, fmt.Errorf("neither name nor label selector specified in ResourceRef")
}
